package com.lenovo.wxtoken.service;

import com.alibaba.fastjson.JSONObject;
import com.lenovo.wxtoken.annotation.OauthCache;
import com.lenovo.wxtoken.entity.OauthCacheSin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class OauthService {

    @Value("${api.wx.token}")
    private String tokenUrl;

    @Value("${api.wx.ticket}")
    private String ticketUrl;

    @Autowired
    private RestTemplate restTemplate;

    @OauthCache()
    public String getAccessToken(String corpId, String secret) throws Exception{
        Map<String, String> param = new HashMap<>();
        param.put("ID", corpId);
        param.put("SECRET", secret);
        JSONObject result = restTemplate.getForObject(tokenUrl, JSONObject.class, param);
        Integer errcode = result.getInteger("errcode");
        if(errcode == 0){
            log.info("get access token from weixin.com, corpId {}", corpId);
            return result.getString("access_token");
        } else {
            log.error("get access token error, errcode: {}, errmsg: {}", errcode, result.getString("errmsg"));
            throw new Exception(errcode+":"+result.getString("errmsg"));
        }

    }

    @OauthCache(prefix = "ticket")
    public String getJsTicket(String token) throws Exception{
        if(StringUtils.isEmpty(token)){
            throw new Exception("获取ticket失败，token不能为空");
        }
        Map<String, String> param = new HashMap<>();
        param.put("ACCESS_TOKEN", token);
        JSONObject result = restTemplate.getForObject(ticketUrl, JSONObject.class, param);
        Integer errcode = result.getInteger("errcode");
        if(errcode == 0){
            log.info("get jsapi tiket from weixin.com, token {}", token);
            return result.getString("ticket");
        } else {
            log.error("get jsapi tiket error, errcode: {}, errmsg: {}", errcode, result.getString("errmsg"));
            throw new Exception(errcode+":"+result.getString("errmsg"));
        }

    }

    @OauthCache(prefix = "config")
    public String getConfig(String corpId, String agentId, String jsTicket, String url) throws Exception{
        if(StringUtils.isEmpty(jsTicket)){
            throw new Exception("获取jsConfig失败，ticket不能为空");
        }
        String nonce = "welldone";
        Long timeStamp = System.currentTimeMillis()/1000;
        String signature = getJsApiSingnature(url, nonce, timeStamp, jsTicket);

        JSONObject config = new JSONObject();
        config.fluentPut("agentId", agentId)
                .fluentPut("corpId", corpId)
                .fluentPut("timeStamp", String.valueOf(timeStamp))
                .fluentPut("nonceStr", nonce)
                .fluentPut("signature", signature);
//        log.info("ticket {}, nonStr {}, timeStrap {}, url {}, sing {}", jsTicket, nonce, timeStamp, url, signature);

        return config.toJSONString();
    }

    private String getJsApiSingnature (String url, String nonce, Long timeStamp, String jsTicket) throws Exception {
        String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonce + "&timestamp=" + timeStamp + "&url=" + url;
        String signature = "";

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(plainTex.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
            return signature;
        } catch (Exception var7) {
            throw new Exception("errcode:900006 errmsg:签名计算失败");
        }
    }

    private String byteToHex(byte[] hash) {
        Formatter formatter = new Formatter();
        byte[] var2 = hash;
        int var3 = hash.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            byte b = var2[var4];
            formatter.format("%02x", b);
        }

        String result = formatter.toString();
        formatter.close();
        return result;
    }


    public String getExpire(){
        return OauthCacheSin.getInstance().get("expire");
    }

    @Scheduled(fixedRate = 6600000)
    public void refreshExpire() {
        OauthCacheSin.getInstance().clear();

        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        OauthCacheSin.getInstance().put("expire", df.format(localDateTime.plusMinutes(110)));
        log.info("----------->   Clear all cached information at {}", localDateTime);
    }

}

